using System;
using System.Diagnostics;
using System.Text;
using System.Web.UI.WebControls.WebParts;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;
using System.IO;
using System.Collections.Generic;
using DE.Sdc.SharePoint.SPContentStructure.Common;

namespace DE.Sdc.SharePoint.SPContentStructure.Import
{
    [Serializable]
    [XmlType(AnonymousType = true, Namespace = DeploymentConstants.Namespace)]
    [XmlRoot(Namespace = DeploymentConstants.Namespace, IsNullable = false)]
    public class WebPart : HierarchicalElement<Page>, IImportDefinition<System.Web.UI.WebControls.WebParts.WebPart, SPLimitedWebPartManager>
    {
        public WebPart()
        {
            Properties = new List<Property>();
        }

        /// <remarks/>
        [XmlArrayItem("Property")]
        public List<Property> Properties { get; set; }

        [XmlIgnore]
        public bool PropertiesSpecified
        {
            get
            {
                return Properties != null && Properties.Count > 0;
            }
        }

        /// <remarks/>
        [XmlAttribute]
        public string Zone { get; set; }

        /// <remarks/>
        [XmlAttribute]
        public int Order { get; set; }

        /// <remarks/>
        [XmlAttribute]
        public string ImportXml { get; set; }

        [XmlIgnore]
        public System.Web.UI.WebControls.WebParts.WebPart UpdatedSPObject { get; internal set; }

        /// <summary>
        /// Creates a webpart in a given webpart manager
        /// </summary>
        /// <param name="webPartManager">The webpart manager where to create the webpart</param>
        /// <returns></returns>
        private System.Web.UI.WebControls.WebParts.WebPart CreateWebPart(SPLimitedWebPartManager webPartManager)
        {
            Trace.WriteLine("Try to create WebPart '" + Title + "' in '" + Zone + "'.", "ContentStructureImporter:CreateWebPart");

            XmlTextReader xmlReader = null;

            try
            {
                string errorMessage;
                string filePath = File.GetFeatureRootedPath(ImportXml);
                StringReader webPartXmlReader = new StringReader(Encoding.UTF8.GetString(DeploymentHelper.ReadFile(filePath, Encoding.UTF8)));

                xmlReader = new XmlTextReader(webPartXmlReader);
                System.Web.UI.WebControls.WebParts.WebPart webPart = webPartManager.ImportWebPart(xmlReader, out errorMessage);
                webPart.ID = Title ?? webPart.ID;
                webPartManager.AddWebPart(webPart, Zone, Order);

                return webPart;
            }
            catch (Exception ex)
            {
                throw new ContentStructureException(
                    "Error while importing webpart file '" + ImportXml + "'", ex);
            }
            finally
            {
                if (xmlReader != null)
                    xmlReader.Close();

                Trace.WriteLine("WebPart '" + Title + "' in '" + Zone + "' created.", "ContentStructureImporter:ImportItem");
            }
        }

        /// <summary>
        /// Adds, Replaces or Deletes, Modifies or Moves a webpart in a given webpart manager
        /// </summary>
        /// <param name="webPart">A webpart based on the webPartDefinition or null</param>
        /// <param name="webPartManager">The parent webPartManager where to insert the webpart</param>
        public void ImportDefinition(System.Web.UI.WebControls.WebParts.WebPart webPart, SPLimitedWebPartManager webPartManager)
        {
            Trace.WriteLine("Try to import WebPart '" + Title + "' in '" + Zone + "'.", "ContentStructureImporter:ImportWebPart");
            foreach (Property property in Properties)
            {
                property.Value = DeploymentHelper.Resolve(property.Value, webPartManager.Web.Locale);
            }
            
            if (webPart == null)
            {
                if (Action == ActionType.AddOrUpdate || Action == ActionType.Replace)
                    webPart = CreateWebPart(webPartManager);
                else
                    return;
            }
            else if (Action == ActionType.Replace)
            {
                webPartManager.DeleteWebPart(webPart);
                webPart = CreateWebPart(webPartManager);
            }
            else if (Action == ActionType.Delete)
            {
                webPartManager.DeleteWebPart(webPart);
                return;
            }

            if (webPart.IsClosed)
            {
                webPartManager.OpenWebPart(webPart);
                webPartManager.MoveWebPart(webPart, Zone, Order);
                webPartManager.SaveChanges(webPart);
            }

            Trace.WriteLine("WebPart '" + Title + "' in '" + Zone + "' imported.", "ContentStructureImporter:ImportWebPart");
        }
    }
}